import TWEEN from '@tweenjs/tween.js';

/**
 * TODO: 对于飞入指定物品的触发有两种：
 *  ✅1.由旁侧按钮触发
 *    点击按钮，相机飞入到指定物体
 *  - 获取当前
 *  - 确定结束点坐标（一般由观察点坐标scalar得到）
 *  - 确定结束点的观察点
 *
 *  2.直接点击物品触发
 *     如果是CSS2D/3D的，可直接用click事件（视频上演示的是CSS触发）
 *     如果是3D物品，可能需要把逻辑写到射线检测部分
 */
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
/**
 * 创建相机动画
 * @param option - 动画选项
 */
export function createCameraTween(option: {
  camera: THREE.PerspectiveCamera;
  /** OrbitControls */
  controls: OrbitControls;
  /** 相机动画结束相机位置 */
  endPos: THREE.Vector3;
  /** 相机动画结束lookAt指向的目标观察点 */
  endTarget: THREE.Vector3;
  /** 动画持续时间，默认2000ms */
  duration?: number;
}): void {
  const { camera, controls, endPos, endTarget, duration = 2000 } = option;

  // 定义动画对象的类型
  type TweenObject = {
    x: number;
    y: number;
    z: number;
    tx: number;
    ty: number;
    tz: number;
  };

  new TWEEN.Tween({
    // 不管相机此刻处于什么状态，直接读取当前的位置和目标观察点
    x: camera.position.x,
    y: camera.position.y,
    z: camera.position.z,
    tx: controls.target.x,
    ty: controls.target.y,
    tz: controls.target.z,
  } as TweenObject)
    .to(
      {
        // 动画结束相机位置坐标
        x: endPos.x,
        y: endPos.y,
        z: endPos.z,
        // 动画结束相机指向的目标观察点
        tx: endTarget.x,
        ty: endTarget.y,
        tz: endTarget.z,
      } as TweenObject,
      duration
    )
    .onUpdate(function (obj: TweenObject) {
      // 动态改变相机位置
      camera.position.set(obj.x, obj.y, obj.z);
      // 动态计算相机视线
      // camera.lookAt(obj.tx, obj.ty, obj.tz);
      controls.target.set(obj.tx, obj.ty, obj.tz);
      controls.update(); //内部会执行.lookAt()
    })
    .start();
}
